﻿using System;
using System.ComponentModel;
using System.Drawing;
using System.Drawing.Design;
using System.Drawing.Imaging;
using System.Globalization;
using System.IO;
using System.Reflection;
using System.Text.RegularExpressions;
using System.Threading;
using System.Windows.Forms;
using Telerik.Charting;
using Telerik.Charting.Styles;
using Telerik.WinControls.UI.Design;
using System.Collections.Generic;
using System.Xml;

namespace Telerik.WinControls.UI
{
    /// <summary>
    /// The class represents the base functionality of the RadChart.
    /// </summary>
    [ToolboxBitmap(typeof (Bitmap)), Description("Telerik RadChart"), Designer(typeof (ChartDesigner)), DefaultEvent("Click")]
    public partial class RadChart : UserControl, ISupportInitialize, IDisposable, IExtenderProvider, IChartComponent
    {
        #region Constants

        private const int radChartDefHeight = 300;
        private const int radChartDefWidth = 400;

        #endregion

        #region Fields

        private string radChartTempImagesFolder;
        private readonly Chart radChartChartingEngine;
        private ChartPrinting radChartPrintingEngine;
        private Bitmap radChartBitmapBuffer;
        private bool radChartShouldRefresh;
		private ToolTip radChartToolTip;
		private Cursor radChartCursor;

        #endregion

        #region Properties

        /// <summary>
        /// Specifies the custom palettes for chart
        /// </summary>
        [Category("Appearance"), Description("Custom figures collection."), Browsable(true), NotifyParentProperty(true), Editor(typeof (CustomFiguresCollectionEditor), typeof (UITypeEditor)), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public CustomFiguresCollection CustomFigures
        {
            get
            {
                for (int i = 0; i < radChartChartingEngine.CustomFigures.Count; i++)
                {
                    CustomFigure figure = radChartChartingEngine.CustomFigures[i];
                    if (String.IsNullOrEmpty(figure.Name))
                    {
                        radChartChartingEngine.CustomFigures.Remove(figure.Name);
                        radChartChartingEngine.Figures.Figures.Remove(figure.Name);
                    }
                }
                return radChartChartingEngine.CustomFigures;
            }
        }

        [Category("Appearance"), Description("Specifies the default type of the data series."), DefaultValue(typeof (ChartSeriesType), "bar")]
        public ChartSeriesType DefaultType
        {
            get
            {
                return radChartChartingEngine.DefaultType;
            }
            set
            {
                radChartChartingEngine.DefaultType = value;
                UpdateGraphics();
            }
        }

        /// <summary>
        /// Specifies AutoLayout mode to all items on the chart control.
        /// </summary>
        [Category("Appearance"), Description("Specifies AutoLayout mode to all items on the chart control."), DefaultValue(false)]
        public bool AutoLayout
        {
            get
            {
                return radChartChartingEngine.AutoLayoutWrapper;
            }
            set
            {
                radChartChartingEngine.AutoLayoutWrapper = value;
            }
        }

        /// <summary>
		/// Specifies AutoLayout mode to all items on the chart control.
		/// </summary>
		[Category("Appearance"), Description("Specifies AutoTextWrap mode for all text blocks of the chart control."), DefaultValue(Charting.DefaultValues.AUTO_TEXT_WRAP)]
		public bool AutoTextWrap
		{
			get
			{
				return radChartChartingEngine.AutoTextWrapWrapper;
			}
			set
			{
				radChartChartingEngine.AutoTextWrapWrapper = value;
			}
		}

        /// <summary>
        /// Specifies the series palette
        /// </summary>
        [Category("Appearance"), DefaultValue(""), NotifyParentProperty(true), Editor(typeof (ChartPaletteEditor), typeof (UITypeEditor))]
        public string SeriesPalette
        {
            get
            {
                return radChartChartingEngine.SeriesPaletteWrapper;
            }
            set
            {
                radChartChartingEngine.SeriesPaletteWrapper = value;
                UpdateGraphics();
            }
        }

        /// <summary>
        /// Chart style
        /// </summary>
        [Category("Appearance"), Description("Chart visual settings")]
        [TypeConverter(typeof (ExpandableObjectConverter)), NotifyParentProperty(true), Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public StyleChart Appearance
        {
            get
            {
                return radChartChartingEngine.Appearance;
            }
        }

        [Category("Appearance"), Description("Specifies the chart's skin"), DefaultValue(Charting.DefaultValues.SKIN_NAME), Editor(typeof (ChartSkinEditor), typeof (UITypeEditor))]
        public string Skin
        {
            get
            {
                return radChartChartingEngine.Skin;
            }
            set
            {
                radChartChartingEngine.Skin = value;
                UpdateGraphics();
            }
        }

        /// <summary>
        /// Should skin override user setting or not
        /// </summary>
        [Category("Appearance"), NotifyParentProperty(true), Description("Should skin override user setting or not"), DefaultValue(Charting.DefaultValues.SKINS_OVERRIDE_STYLES)]
        public bool SkinsOverrideStyles
        {
            get
            {
                return radChartChartingEngine.SkinsOverrideStyles;
            }
            set
            {
                radChartChartingEngine.SkinsOverrideStyles = value;
            }
        }

        /// <summary>
        /// Data management support object
        /// </summary>
        [Category("Data"), Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public DataManager DataManager
        {
            get
            {
                return radChartChartingEngine.DataManager;
            }
        }

        /// <summary>
        /// Collection of the chart's data series.
        /// </summary>		
        [Category("Data"), Description("Series collection."), Browsable(true), NotifyParentProperty(true), Editor(typeof (SeriesCollectionEditor), typeof (UITypeEditor)), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public ChartSeriesCollection Series
        {
            get
            {
                return radChartChartingEngine.Series;
            }
        }

        /// <summary>
        /// Chart height in pixels
        /// </summary>
        [DefaultValue(typeof (int), "300"), NotifyParentProperty(true)]
        public new int Height
        {
            get
            {
                return base.Height;
            }
            set
            {
                if (radChartChartingEngine != null)
                {
                    radChartChartingEngine.Appearance.Dimensions.Height = value;
                }
                base.Height = value;
            }
        }

        /// <summary>
        /// Chart width in pixels
        /// </summary>
        [DefaultValue(typeof (int), "400"), NotifyParentProperty(true)]
        public new int Width
        {
            get
            {
                return base.Width;
            }
            set
            {
                if (radChartChartingEngine != null)
                {
                    radChartChartingEngine.Appearance.Dimensions.Width = value;
                }

                base.Width = value;
            }
        }

        /// <summary>
        /// Gets or sets RadChart's legend object.
        /// </summary>
        [Category("Elements"), Description("Legend settings."), Browsable(true), NotifyParentProperty(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Content), TypeConverter(typeof (ExpandableObjectConverter))]
        public ChartLegend Legend
        {
            get
            {
                return radChartChartingEngine.Legend;
            }
        }

        /// <summary>
        /// Specifies the chart's plot area.
        /// </summary>
        [Category("Elements"), Description("Plot area settings."), Browsable(true), NotifyParentProperty(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public ChartPlotArea PlotArea
        {
            get
            {
                return radChartChartingEngine.PlotArea;
            }
        }

        /// <summary>
        /// The chart title message.
        /// </summary>		
        [MergableProperty(false), Bindable(false), Category("Elements"), Description("The chart title."), NotifyParentProperty(true), Browsable(true), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public ChartTitle ChartTitle
        {
            get
            {
                return radChartChartingEngine.ChartTitle;
            }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override Image BackgroundImage
        {
            get
            {
                return base.BackgroundImage;
            }
            set
            {
                base.BackgroundImage = value;
            }
        }

        [Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public override ImageLayout BackgroundImageLayout
        {
            get
            {
                return base.BackgroundImageLayout;
            }
            set
            {
                base.BackgroundImageLayout = value;
            }
        }

        /// <summary>
        /// Specifies the image format for export
        /// </summary>
        [Category("Settings"), Description("Specifies the image format for export."), Browsable(false), DefaultValue(typeof (ImageFormat), "png")]
        public ImageFormat ChartImageFormat
        {
            get
            {
                return radChartChartingEngine.ImageFormat;
            }
            set
            {
                radChartChartingEngine.ImageFormat = value;
                UpdateGraphics();
            }
        }

        /// <summary>
        /// Specifies the quality at which the text is rendered.
        /// </summary>
        [Category("Appearance"), Description("Specifies the quality at which text is rendered. Better quality assumes more time for rendering."), Browsable(true), DefaultValue(typeof (TextQuality), "AntiAliasGridFit")]
        public TextQuality TextQuality
        {
            get
            {
                return radChartChartingEngine.Appearance.TextQuality;
            }
            set
            {
                radChartChartingEngine.Appearance.TextQuality = value;
                UpdateGraphics();
            }
        }

        /// <summary>
        /// Specifies the custom palettes for chart
        /// </summary>
        [Category("Appearance"), Description("Specifies the custom palettes for chart."), Browsable(true), NotifyParentProperty(true), Editor(typeof (CustomPaletteCollectionEditor), typeof (UITypeEditor)), DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
        public CustomPalettesCollection CustomPalettes
        {
            get
            {
                return radChartChartingEngine.CustomPalettes;
            }
        }

        /// <summary>
        /// Specifies the orientation of chart series on the plot area.
        /// </summary>
        [Category("Appearance"), Description("Specifies the orientation of the chart series on the plot area."), Browsable(true), Bindable(true), DefaultValue(typeof (ChartSeriesOrientation), "Vertical")]
        public ChartSeriesOrientation SeriesOrientation
        {
            get
            {
                return radChartChartingEngine.SeriesOrientation;
            }
            set
            {
                radChartChartingEngine.SeriesOrientation = value;
                UpdateGraphics();
            }
        }

        /// <summary>
        /// Enables / disables Intelligent labels logic for series items labels in all plot areas.
        /// </summary>
        [Category("Appearance"), Description("Enables / disables Intelligent labels logic for series items labels in all plot areas"), Browsable(true), Bindable(true), DefaultValue(typeof(Boolean), "false")]
        public bool IntelligentLabelsEnabled
        {
            get
            {
                return radChartChartingEngine.IntelligentLabelsEnabled;
            }
            set
            {
                radChartChartingEngine.IntelligentLabelsEnabled = value;
                UpdateGraphics();
            }
        }

        #endregion

        #region Public methods

        public event EventHandler<EventArgs> PrePaint;

        public event EventHandler<EventArgs> DataBinding;

        public event EventHandler<EventArgs> DataBound;

        public event EventHandler<EventArgs> BeforeLayout;

        public event EventHandler<ChartItemDataBoundEventArgs> ItemDataBound;
        
        private void OnItemDataBound(ChartItemDataBoundEventArgs args)
        {
            if (ItemDataBound != null)
            {
                ItemDataBound(this, args);
            }
        }

        private void OnDataBinding(EventArgs args)
        {
            if (DataBinding != null)
            {
                DataBinding(this, args);
            }
        }

        private void OnDataBound(EventArgs args)
        {
            if (DataBound != null)
            {
                DataBound(this, args);
            }
        }     

        /// <summary>
        /// Adds a new data series to the RadChart's series collection.
        /// </summary>
        /// <param name="chartSeries"></param>
        [Description("Adds a new series to the chart series collection.")]
        public void AddChartSeries(ChartSeries chartSeries)
        {
            radChartChartingEngine.AddSeries(chartSeries);
        }

        public delegate void ChartClickEventHandler(object sender, ChartClickEventArgs args);

        public new event ChartClickEventHandler Click;

        protected override void OnClick(EventArgs e)
        {
            base.OnClick(e);
            MouseEventArgs me = (MouseEventArgs)e;
            IActiveRegion iar = radChartChartingEngine.CallRegionEvent(new Point(me.X, me.Y));
        				
    		if( iar != null && Click != null )
            {
				ChartSeriesItem csi = null;
				ChartSeries cs = null;

				if( iar is ChartSeriesItem )
					csi = (ChartSeriesItem) iar;
				else if( iar is BindableLegendItem || iar is ChartMarker )
                {
					BindableLegendItem bli;
					if( iar is ChartMarker )
						bli = ((BindableLegendItem)((ChartMarker)iar).Parent);
					else
						bli = (BindableLegendItem)iar;

					if( bli.BindableLegendItemSource is ChartSeriesItem )
						csi = (ChartSeriesItem)bli.BindableLegendItemSource;
					else
						cs = bli.BindableLegendItemSource as ChartSeries;
                }

				if( csi != null )
					cs = csi.Parent;
				Click(this, new ChartClickEventArgs(iar, cs, csi));
            }
        }

		protected override void OnMouseMove(MouseEventArgs e)
		{
			base.OnMouseMove(e);
			MouseEventArgs me = (MouseEventArgs)e;
			List<IActiveRegion> iar = ActiveRegion.GetActiveRegions(new Point(me.X, me.Y), radChartChartingEngine);

			if (radChartCursor == null)
				radChartCursor = this.Cursor;

			if (iar.Count > 0)
			{
				foreach (IActiveRegion region in iar)
				{
					if (!string.IsNullOrEmpty(region.ActiveRegion.Tooltip))
					{
						radChartToolTip.SetToolTip(this, region.ActiveRegion.Tooltip);
						break;
					}
					if ((Click != null) && ((region is ChartSeriesItem) || ( region is BindableLegendItem)))
					{
						this.Cursor = Cursors.Hand;
					}
				}
			}
			else
			{
				radChartToolTip.SetToolTip(this, "");
				this.Cursor = radChartCursor;
			}
		}

        #endregion

        #region Constructors

        /// <summary>
        /// Creates a new instance of RadChart.
        /// </summary>
        public RadChart()
        {
            DoubleBuffered = true;
			radChartToolTip = new ToolTip();
            base.Height = radChartDefHeight;
            base.Width = radChartDefWidth;

            Resize += Chart_SizeChanged;
            SizeChanged += Chart_SizeChanged;

            radChartTempImagesFolder = string.Empty;
            radChartChartingEngine = new Chart(this);
            DataManager.ItemDataBound += DataManager_ItemDataBound;
            Chart.BeforeLayoutEventHandler += Chart_BeforeLayout;
            Chart.PrePaintEventHandler += Chart_PrePaint;
        }

        private void Chart_BeforeLayout(object sender, EventArgs e)
        {
            if (BeforeLayout != null)
            {
                BeforeLayout(sender, e);
            }
        }

        private void Chart_PrePaint(object sender, EventArgs e)
        {
            if (PrePaint != null)
            {
                PrePaint(sender, e);
            }
        }

        private void DataManager_ItemDataBound(object sender, ChartItemDataBoundEventArgs e)
        {
            OnItemDataBound(e);
        }

        #endregion

        #region RadChart's API functions

        /// <summary>
        /// Resets current chart's skin to default
        /// </summary>
        public void ClearSkin()
        {
            radChartChartingEngine.ClearSkin(this.Chart);
            Invalidate();
        }

        /// <summary>
        /// Loads user skin from a TextWriter object
        /// </summary>
        /// <param name="text">TextWriter object</param>
        public void LoadSkin(TextWriter text)
        {
            radChartChartingEngine.LoadSkin(this.Chart, text);
            Invalidate();
        }

        /// <summary>
        /// Exports current chart's skin into TextWriter object
        /// </summary>
        /// <returns></returns>
        public TextWriter SaveSkin()
        {
            return radChartChartingEngine.SaveSkin(this.Chart);
        }

        /// <summary>
        /// Exports current chart's settings into TextWriter object
        /// </summary>
        /// <returns></returns>
        public TextWriter SaveToXml()
        {
            return radChartChartingEngine.SaveChart(this);
        }

        /// <summary>
        /// Loads entire chart settings from a TextWriter object
        /// </summary>
        /// <param name="text">TextWriter object</param>
        public void LoadFromXml(TextReader reader)
        {
            radChartChartingEngine.LoadChart(this, reader);
        }

        /// <summary>
        /// Saves the chart's state into XML file in the specified by fileName location.
        /// </summary>
        /// <param name="fileName">Path to the file</param>
        [Description("Saves the chart contents into an Xml file")]
        public void SaveToXml(string fileName)
        {
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.LoadXml(SaveToXml().ToString());
            xmlDocument.Save(this.MapPath(fileName));
        }

        /// <summary>
        /// Loads RadChart's settings and data from external XML file.
        /// </summary>
        /// <param name="relativeFileName"></param>
        [Description("Loads an Xml file and populates the chart's properties")]
        public void LoadFromXml(string relativeFileName)
        {
            CultureInfo originalCI = Thread.CurrentThread.CurrentCulture;

            Thread.CurrentThread.CurrentCulture = new CultureInfo("En-us");

            Clear();
            XmlDocument xml = new XmlDocument();
            xml.Load(this.MapPath(relativeFileName));
            TextReader reader = new StringReader(xml.OuterXml);

            this.LoadFromXml(reader);

            Thread.CurrentThread.CurrentCulture = originalCI;
        }

		/// <summary>
		/// Clone RadChart object
		/// </summary>
		/// <returns>New instance of RadChart</returns>
        public object Clone()
        {
            RadChart clone = new RadChart();
			clone.Chart.CopyFrom(this.Chart);
            clone.Chart.DesignTime = Chart.DesignTime;
            clone.DataSource = DataSource;
            clone.DataMember = DataMember;
            return clone;
        }


        /// <summary>
        /// Removes chart's data series and axis items.
        /// </summary>
        [Description("Clears all chart collections: series collection and axis items.")]
        public void Clear()
        {
            radChartChartingEngine.Series.RemoveSeries();
        }

        [Description("Removes only the series from the series collection.")]
        /// <summary>
        /// Removes all data series from the series collection without removing axis items.
        /// </summary>
        public void RemoveAllSeries()
        {
            radChartChartingEngine.RemoveAllSeries();
        }

        [Description("Removes the series at the specified series index.")]
        /// <summary>
        /// Removes the data series at the specified index.
        /// </summary>
        /// <param name="seriesIndex"></param>
        public void RemoveSeriesAt(int seriesIndex)
        {
            radChartChartingEngine.RemoveSeriesAt(seriesIndex);
        }

        [Description("Gets the series from the series collection at the specified index.")]
        /// <summary>
        /// Gets a reference to the data series object at the specified index.
        /// </summary>
        /// <param name="seriesIndex"></param>
        /// <returns></returns>
        public ChartSeries GetSeries(int seriesIndex)
        {
            if ((seriesIndex >= 0) && (seriesIndex < radChartChartingEngine.Series.Count))
            {
                return radChartChartingEngine.Series[seriesIndex];
            }
            else
            {
                return null;
            }
        }

        [Description("Gets the series from the series collection with the specified name.")]
        /// <summary>
        /// Gets a reference to the data series object with the specified name.
        /// </summary>
        /// <param name="seriesName"></param>
        /// <returns></returns>
        public ChartSeries GetSeries(string seriesName)
        {
            return radChartChartingEngine.Series.GetByName(seriesName);
        }

        /// <summary>
        /// Gets a reference to the data series object with the specified color.
        /// </summary>
        /// <param name="seriesColor"></param>
        /// <returns></returns>
        [Description("Gets the series from the series collection with the specified color.")]
        public ChartSeries GetSeries(Color seriesColor)
        {
            return radChartChartingEngine.GetSeries(seriesColor);
        }

        /// <summary>
        /// Creates a new chart series and adds it to the series collection.
        /// </summary>
        /// <param name="seriesName"></param>
        /// <param name="mainColor"></param>
        /// <param name="secondColor"></param>
        /// <param name="chartSeriesType"></param>
        /// <returns></returns>
        [Description("Creates a new series, adds it to the series collection and returns a reference to it.")]
        public ChartSeries CreateSeries(string seriesName, Color mainColor, Color secondColor, ChartSeriesType chartSeriesType)
        {
            ChartSeries series = new ChartSeries(seriesName, chartSeriesType);
            series.Appearance.FillStyle.MainColor = mainColor;
            series.Appearance.FillStyle.SecondColor = secondColor;
            series.Appearance.LineSeriesAppearance.Color = mainColor;
            series.Appearance.PointMark.Chart = this.radChartChartingEngine;
            series.Appearance.LabelAppearance.Chart = this.radChartChartingEngine;
            Series.Add(series);
            return series;
        }

        /// <summary>
        /// Saves the chart with the specified file name.
        /// </summary>
        /// <param name="filename"></param>
        [Description("Saves the chart as an image in format specified by ChartImageFormat property.")]
        public void Save(string filename)
        {
            Save(filename, ChartImageFormat);
        }

        [Description("Saves the chart as an image with the specified ImageFormat.")]
        /// <summary>
        /// Saves the chart with the specified file name and the specified image format.
        /// </summary>
        /// <param name="filename"></param>
        /// <param name="imageFormat"></param>
        public void Save(string filename, ImageFormat imageFormat)
        {
            if (imageFormat == ImageFormat.Emf)
            {
                ImageFormat oldFormat = ChartImageFormat;
                ChartImageFormat = ImageFormat.Emf;
                GetBitmap();

                if (File.Exists(radChartChartingEngine.TempImagePath))
                {
                    try
                    {
                        File.Copy(radChartChartingEngine.TempImagePath, filename, true);
                    }
                    catch (Exception ex)
                    {
                        MessageBox.Show("Can not export chart image. " + ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    }

                    try
                    {
                        File.Delete(radChartChartingEngine.TempImagePath);
                    }
                    catch
                    {
                        return;
                    }
                }
                ChartImageFormat = oldFormat;
                GetBitmap();
            }
            else
            {
                Image img = GetBitmap();
                img.Save(filename, imageFormat);
                img.Dispose();
            }
        }

        public Image GetBitmap()
        {
            return radChartChartingEngine.GetImage(Width, Height);
        }

        #endregion

        #region Inherited propeties

        #region Hidden

        [Browsable(false)]
        [DesignerSerializationVisibility(0)]
        [Bindable(false)]
        public override Size MaximumSize
        {
            get
            {
                return base.MaximumSize;
            }
            set
            {
                base.MaximumSize = value;
            }
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(0)]
        [Bindable(false)]
        public override Size MinimumSize
        {
            get
            {
                return base.MinimumSize;
            }
            set
            {
                base.MinimumSize = value;
            }
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(0)]
        [Bindable(false)]
        public Color BorderColor
        {
            get
            {
                return new Color();
            }
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(0)]
        [Bindable(false)]
        public override Font Font
        {
            get
            {
                return base.Font;
            }
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(0)]
        [Bindable(false)]
        public override Color ForeColor
        {
            get
            {
                return new Color();
            }
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(0)]
        [Bindable(false)]
        public override Color BackColor
        {
            get
            {
                return Color.Empty;
            }
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(0)]
        [Bindable(false)]
        public override RightToLeft RightToLeft
        {
            get
            {
                return base.RightToLeft;
            }
            set
            {
                base.RightToLeft = value;
            }
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(0)]
        [Bindable(false)]
        public override bool AutoScroll
        {
            get
            {
                return base.AutoScroll;
            }
            set
            {
                base.AutoScroll = value;
            }
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(0)]
        [Bindable(false)]
        public new Size AutoScrollMargin
        {
            get
            {
                return base.AutoScrollMargin;
            }
            set
            {
                base.AutoScrollMargin = value;
            }
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(0)]
        [Bindable(false)]
        public new Size AutoScrollMinSize
        {
            get
            {
                return base.AutoScrollMinSize;
            }
            set
            {
                base.AutoScrollMinSize = value;
            }
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(0)]
        [Bindable(false)]
        public override bool AutoSize
        {
            get
            {
                return base.AutoSize;
            }
            set
            {
                base.AutoSize = value;
            }
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(0)]
        [Bindable(false)]
        public new AutoSizeMode AutoSizeMode
        {
            get
            {
                return base.AutoSizeMode;
            }
            set
            {
                base.AutoSizeMode = value;
            }
        }

        #endregion

        #region Data Binding members

        /// <summary>
        /// The DataSource object
        /// </summary>
        /// <remarks>Gets or sets the object from which the chart control retrieves its list of data items</remarks>
        [Category("Data"), DefaultValue(null), AttributeProvider(typeof (IListSource)), RefreshProperties(RefreshProperties.Repaint)]
        public object DataSource
        {
            get
            {
                return DataManager.DataSource;
            }
            set
            {
                if (radChartChartingEngine.DesignTime && DataManager.DataSource != null && DataManager.DataSource != value)
                {
                    PlotArea.XAxis.ClearDataBoundState();
                    Series.ClearDataBoundState();
                    DataManager.UseSeriesGrouping = true;
                }

                DataManager.DataSource = value;

                UpdateGraphics();
            }
        }

        /// <summary>
        /// Gets or sets the name of the list of data that the data-bound control binds to, in cases where the data source contains more than one distinct list of data items.
        /// </summary>
        [Category("Data")]
        [DefaultValue("")]
        [RefreshProperties(RefreshProperties.Repaint)]
        [Editor("System.Windows.Forms.Design.DataMemberListEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof (UITypeEditor))]
        public string DataMember
        {
            get
            {
                return radChartChartingEngine.DataManager.DataMember;
            }
            set
            {
                radChartChartingEngine.DataManager.DataMember = value;
                UpdateGraphics();
            }
        }

        /// <summary>
        /// Binds a data source to the invoked control
        /// </summary>
        public void DataBind()
        {
            // Call data binding
            DataManager.IsDataBindCalled = false;

            // Raise the DataBinding event. 
            OnDataBinding(EventArgs.Empty);
            
            // Data binding
            DataManager.DataBind();

            // Raise the DataBound event.
            OnDataBound(EventArgs.Empty);

            // Update picture
            UpdateGraphics();
        }

        /// <summary>
        /// Gets or sets the name of the DataSource column (member) that will be used to split one column data into several chart Series
        /// </summary>
        [Category("Data"), Description("Name of the DataSource column (member) that will be used to split Y values from one column into several chart Series"), Editor(typeof (DataColumnEditor), typeof (UITypeEditor)), DefaultValue("")]
        public string DataGroupColumn
        {
            get
            {
                return radChartChartingEngine.DataGroupColumn;
            }
            set
            {
                if (String.Compare(value,"(None)", true) == 0)
                {
                    radChartChartingEngine.DataManager.UseSeriesGrouping = false;
                    radChartChartingEngine.DataGroupColumn = String.Empty;
                }
                else
                {
                    radChartChartingEngine.DataManager.UseSeriesGrouping = true;
                    radChartChartingEngine.DataGroupColumn = value;
                }
                UpdateGraphics();
            }
        }

        #endregion

        private void Chart_SizeChanged(object sender, EventArgs e)
        {
            radChartChartingEngine.Appearance.Dimensions.SetDimensions(Width, Height);
            UpdateGraphics();
        }

        private Bitmap GetImage()
        {
            if ((radChartShouldRefresh) || (null == radChartBitmapBuffer))
            {
                if (null != radChartBitmapBuffer)
                {
                    radChartBitmapBuffer.Dispose();
                }

                radChartBitmapBuffer = new Bitmap(radChartChartingEngine.GetImage());

                radChartShouldRefresh = false;
            }

            return radChartBitmapBuffer;
        }

        protected override void OnPaint(PaintEventArgs e)
        {
            e.Graphics.DrawImage(GetImage(), 0, 0);
        }

        protected override void OnLoad(EventArgs e)
        {
            base.OnLoad(e);
            if (ParentForm != null)
            {
                ParentForm.Load += ParentForm_Load;
            }
        }

        public void UpdateGraphics()
        {
            radChartShouldRefresh = true;
            Invalidate();
        }

        public override void Refresh()
        {
            radChartShouldRefresh = true;
            base.Refresh();
        }

        #endregion

        #region Internal methods

        private void ParentForm_Load(object sender, EventArgs e)
        {
            if (!DataManager.IsDataBindCalled && DataManager.DataSource != null)
            {
                DataBind();
            }
        }

        #endregion

        #region Printing Support

        /// <summary>
        /// Printing manager
        /// </summary>
        [Category("Printing"), Browsable(false), DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public ChartPrinting Printing
        {
            get
            {
                if (radChartPrintingEngine == null)
                {
                    radChartPrintingEngine = new ChartPrinting(this);
                }

                return radChartPrintingEngine;
            }
        }

        #endregion

        #region ISupportInitialize Members

        public void BeginInit()
        {
        }

        public void EndInit()
        {
        }

        #endregion

        #region IDisposable Members

        private bool disposed;

        void IDisposable.Dispose()
        {
            // Check to see if Dispose has already been called.
            if (!disposed)
            {
                Dispose();
            }
            disposed = true;
        }

        #endregion

        #region IExtenderProvider Members

        public bool CanExtend(object extendee)
        {
            return true;
        }

        #endregion

        #region ControlVersion Class

        public class ControlVersion : IFormattable
        {
            private Version assemblyVersion;

            public ControlVersion()
            {
                Assembly current = Assembly.GetExecutingAssembly();
                assemblyVersion = current.GetName().Version;
            }

            public string MajorMinor
            {
                get
                {
                    return ToString("$m.$n");
                }
            }

            public string MajorMinorBuild
            {
                get
                {
                    return ToString("$m.$n.$b");
                }
            }

            public string MajorMinorAsUrl
            {
                get
                {
                    return ToString("$m_$n");
                }
            }

            public string MajorMinorBuildAsUrl
            {
                get
                {
                    return ToString("$m_$n_$b");
                }
            }

            public override string ToString()
            {
                return ToString("$m.$n.$b.$r", null);
            }

            public string ToString(string format)
            {
                return ToString(format, null);
            }

            private Regex _regex = new Regex(@"(\$[mnbr])", RegexOptions.IgnoreCase);

            #region IFormattable Members

            public string ToString(string format, IFormatProvider formatProvider)
            {
                return _regex.Replace(format, new MatchEvaluator(MatchEval));
            }

            #endregion

            private string MatchEval(Match m)
            {
                switch (m.Value.ToLower())
                {
                    case "$m": // Major
                        return assemblyVersion.Major.ToString();

                    case "$n": // Minor
                        return assemblyVersion.Minor.ToString();

                    case "$b": // Build
                        return assemblyVersion.Build.ToString();

                    case "$r": // Revision
                        return assemblyVersion.Revision.ToString();
                }

                return (m.Value);
            }
        }

        #endregion

        #region IChartComponent Members

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [DefaultValue("")]
        public string TempImagesFolder
        {
            get
            {
                return radChartTempImagesFolder;
            }
            set
            {
                radChartTempImagesFolder = value;
            }
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public string MapPath(string filePath)
        {
            return filePath;
        }

        [Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public Chart Chart
        {
            get
            {
                return radChartChartingEngine;
            }
        }

        #endregion
    }

	[Obsolete ("This class is obsolete. Please use Telerik.Charting.ChartException")]
    public class ChartException : Exception
    {
        public ChartException(string message, Exception innerException) : base(message, innerException)
        {
        }

        public ChartException(string message) : base(message)
        {
        }

        public ChartException()
        {
        }
    }
}